/**
 * Copyright (C) 2015-2018 IQIYI
 * All rights reserved.
 *
 * Author     : 王海斌
 * E-mail     : wanghaibin@qiyi.com
 * Version    :
 * Date       : Tue 03 Apr 2018 03:44:13 PM CST
 * Destription: 获取磁盘挂载信息
 *
 */
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <string>

static void unescape_tab (char *str)
{
  size_t i, j = 0;
  size_t len = strlen (str) + 1;
  for (i = 0; i < len; i++)
    {
      if (str[i] == '\\' && (i + 4 < len)
          && str[i + 1] >= '0' && str[i + 1] <= '3'
          && str[i + 2] >= '0' && str[i + 2] <= '7'
          && str[i + 3] >= '0' && str[i + 3] <= '7')
        {
          str[j++] = (str[i + 1] - '0') * 64 +
                     (str[i + 2] - '0') * 8 +
                     (str[i + 3] - '0');
          i += 3;
        }
      else
        str[j++] = str[i];
    }
}

void GetMountInfo()
{
    char const *mountinfo = "/proc/self/mountinfo";
    FILE *fp = fopen (mountinfo, "r");
    if (fp != NULL)
    {
        char *line = NULL;
        size_t buf_size = 0;
        while (getline (&line, &buf_size, fp) != -1)
        {
            unsigned int devmaj, devmin;
            int target_s, target_e, type_s, type_e;
            int source_s, source_e, mntroot_s, mntroot_e;
            char test;
            char *dash;
            int rc;

            rc = sscanf(line, "%*u "        /* id - discarded  */
                    "%*u "        /* parent - discarded */
                    "%u:%u "      /* dev major:minor  */
                    "%n%*s%n "    /* mountroot */
                    "%n%*s%n"     /* target, start and end  */
                    "%c",         /* more data...  */
                    &devmaj, &devmin,
                    &mntroot_s, &mntroot_e,
                    &target_s, &target_e,
                    &test);

            if (rc != 3 && rc != 7)  /* 7 if %n included in count.  */
                continue;

            /* skip optional fields, terminated by " - "  */
            dash = strstr (line + target_e, " - ");
            if (! dash)
                continue;

            rc = sscanf(dash, " - "
                    "%n%*s%n "    /* FS type, start and end  */
                    "%n%*s%n "    /* source, start and end  */
                    "%c",         /* more data...  */
                    &type_s, &type_e,
                    &source_s, &source_e,
                    &test);
            if (rc != 1 && rc != 5)  /* 5 if %n included in count.  */
                continue;

            /* manipulate the sub-strings in place.  */
            line[mntroot_e] = '\0';
            line[target_e] = '\0';
            dash[type_e] = '\0';
            dash[source_e] = '\0';
            unescape_tab (dash + source_s);
            unescape_tab (line + target_s);
            unescape_tab (line + mntroot_s);

            //std::string devName=dash + source_s;
            if(strchr(dash + source_s,'/') ) {
                printf("dev_name=%s,           mount_dir=%s, root=%s, type=%s\n", dash + source_s, line + target_s,
                        line + mntroot_s, dash + type_s);
            }
            //  me = xmalloc (sizeof *me);

            //  me->me_devname = xstrdup (dash + source_s);
            //  me->me_mountdir = xstrdup (line + target_s);
            //  me->me_mntroot = xstrdup (line + mntroot_s);
            //  me->me_type = xstrdup (dash + type_s);
            //  me->me_type_malloced = 1;
            //  me->me_dev = makedev (devmaj, devmin);
            //  /* we pass "false" for the "Bind" option as that's only
            //     significant when the Fs_type is "none" which will not be
            //     the case when parsing "/proc/self/mountinfo", and only
            //     applies for static /etc/mtab files.  */
            //  me->me_dummy = ME_DUMMY (me->me_devname, me->me_type, false);
            //  me->me_remote = ME_REMOTE (me->me_devname, me->me_type);

            /* Add to the linked list. */
            //*mtail = me;
            //mtail = &me->me_next;
        }

        free (line);

        if (ferror (fp))
        {
            int saved_errno = errno;
            fclose (fp);
            errno = saved_errno;
            printf("faile\n");
        }

        if (fclose (fp) == EOF)
            printf("faile\n");
    }
}

int main(int argc, char *argv[])
{
    GetMountInfo();
    return 0;
}
